library xapp_utils;

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:encrypt/encrypt.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_album_save/flutter_album_save.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:device_info/device_info.dart';
import 'package:android_device/android_device.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:flutter/material.dart';
import 'package:package_info/package_info.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:xapp_utils/download_utils.dart';
import 'src/loading_dialog_utils.dart';
import 'src/permission_utils.dart';
export 'src/permission_utils.dart';
import 'src/toast_utils.dart';

class XAppUtils {
  static XAppUtils? _instance;

  static XAppUtils getInstance() {
    if (_instance == null) {
      _instance = new XAppUtils._();
    }
    return _instance!;
  }

  BuildContext? _context;
  double? _mediaWidth;
  double? _mediaHeight;
  double? _adaptWidth;
  String? _deviceId;
  String? _deviceType;
  String? _osVersion;
  String? _appVersion;

  XAppUtils._();

  /// 初始化
  /// [context] 上下文
  /// [uiWidth] UI尺寸宽度
  void init({@required BuildContext? context, double uiWidth = 375}) async {
    Size size = MediaQuery.of(context!).size;
    _context = context;
    _mediaWidth = size.width;
    _mediaHeight = size.height;
    _adaptWidth = _mediaWidth! / uiWidth;
    var packageInfo = await PackageInfo.fromPlatform();
    _appVersion = packageInfo.version;
  }

  BuildContext getContext() {
    return _context!;
  }

  /// 获取屏幕宽度
  double getMediaWidth() {
    return _mediaWidth!;
  }

  /// 获取屏幕高度
  double getMediaHeight() {
    return _mediaHeight!;
  }

  /// 根据UI单位转换成rpx
  double rpx(num px) {
    return (px * _adaptWidth!).toDouble();
  }

  /// 显示toast
  void toast(String msg,
      [Duration duration = const Duration(milliseconds: 1500)]) {
    ToastUtils.getInstance().show(msg, duration);
  }

  /// 显示loading，全局只能显示一个
  void showLoading([String msg = '请稍后']) {
    LoadingDialogUtils.getInstance().show(msg: msg);
  }

  /// 隐藏loading
  void hideLoading() {
    LoadingDialogUtils.getInstance().hide();
  }

  /// sha1编码
  String sha1(String data) {
    var bytes = utf8.encode(data);
    var digest = crypto.sha1.convert(bytes);
    return digest.toString();
  }

  /// md5编码
  String md5(String data) {
    var bytes = utf8.encode(data);
    var digest = crypto.md5.convert(bytes);
    return digest.toString();
  }

  /// 获取rsa密钥
  Future<String> getRSAKeyByAsset(String file) async {
    var keyStr = await rootBundle.loadString(file);
    return keyStr;
  }

  dynamic _parseRSAKey(String str) {
    return RSAKeyParser().parse(str);
  }

  // rsa公钥加密
  Future<String> encryptRsaPublic(String key, String data) async {
    final rsaKeyStr = await getRSAKeyByAsset(key);
    final publicKey = _parseRSAKey(rsaKeyStr);
    final encrypter = Encrypter(RSA(publicKey: publicKey));
    final encrypted = encrypter.encrypt(data);
    return encrypted.base64;
  }

  // rsa公钥解密
  Future<String> decryptRsaPublic(String key, String data) async {
    var rsaKeyStr = await getRSAKeyByAsset(key);
    var publicKey = _parseRSAKey(rsaKeyStr);
    final encrypter = Encrypter(RSA(publicKey: publicKey));
    return encrypter.decrypt64(data);
  }

  /// 获取设备ID
  Future<String> getDeviceId() async {
    if (_deviceId == null) {
      if (Platform.isIOS) {
        var info = await DeviceInfoPlugin().iosInfo;
        _deviceId = info.identifierForVendor;
      } else {
        _deviceId = await AndroidDevice.getDeviceId();
      }
    }

    return _deviceId!;
  }

  /// 获取设备类型,如: iPod7,1
  Future<String> getDeviceType() async {
    if (_deviceType == null) {
      if (Platform.isAndroid) {
        AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
        _deviceType = info.model;
      } else {
        IosDeviceInfo info = await DeviceInfoPlugin().iosInfo;
        _deviceType = info.model;
      }
    }

    return _deviceType!;
  }

  /// 获取系统类型,如: ios、android
  String getOsType() {
    return Platform.operatingSystem;
  }

  /// 获取系统版本号,如: 10
  Future<String> getOsVersion() async {
    if (_osVersion == null) {
      if (Platform.isAndroid) {
        AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
        _osVersion = info.version.release;
      } else {
        IosDeviceInfo info = await DeviceInfoPlugin().iosInfo;
        _osVersion = info.systemVersion;
      }
    }

    return _osVersion!;
  }

  /// 获取app版本号,如: 1.0.0
  String getAppVersion() {
    return _appVersion!;
  }

  /// 判断是否有权限
  Future<Map<Permission, PermissionUtilsStatus>> hasPermissions(
      {@required List<Permission>? permissions}) {
    return PermissionUtils.getInstance().has(permissions: permissions);
  }

  /// 判断是否有权限
  Future<PermissionUtilsStatus> hasPermission(Permission permission) {
    return PermissionUtils.getInstance().hasOne(permission);
  }

  /// 请求权限
  Future<Map<Permission, PermissionUtilsStatus>> requestPermissions(
      {@required List<Permission>? permissions}) {
    return PermissionUtils.getInstance().request(permissions: permissions);
  }

  /// 请求权限
  Future<PermissionUtilsStatus> requestPermission(Permission permission) {
    return PermissionUtils.getInstance().requestOne(permission);
  }

  /// 打开app设置页面
  Future<bool> openAppSetting() {
    return PermissionUtils.getInstance().openAppSetting();
  }

  /// 设置剪贴板内容
  Future<void> setClipboardText(String text) {
    return Clipboard.setData(ClipboardData(text: text));
  }

  /// 获取剪贴板内容
  Future<String> getClipboardText() async {
    ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
    if (data == null) {
      return '';
    }
    return data.text ?? '';
  }

  /// 保存图片到相册
  Future<bool> saveImageToAlbum(String path) async {
    var result = await FlutterAlbumSave.saveImageToAlbum(path, 'ImageToAlbum');
    return result.status;
  }

  /// 图片转base64
  Future<String> imageFromBase64(String path) async {
    File file = File(path);
    Uint8List bytes = await file.readAsBytes();
    String bs64 = base64Encode(bytes);
    String str = "data:image/png;base64," + bs64;
    return str;
  }

  /// base64 转图片
  Future<String> base64FromImage(String base64Str) async {
    int index = base64Str.indexOf(',');
    if (index > -1) {
      base64Str = base64Str.substring(index + 1);
    }
    Uint8List bytes = base64.decode(base64Str);
    String dir = (await getTemporaryDirectory()).path;
    String name = md5(base64Str);
    String path = "$dir/download/";
    String filePath = "$path$name.png";
    File file = File(filePath);
    Directory directory = Directory(path);
    if (!directory.existsSync()) {
      directory.create();
    }
    if (file.existsSync()) {
      return file.path;
    }
    bool exists = await file.exists();
    if (exists) {
      return path;
    }
    await file.writeAsBytes(bytes);
    return file.path;
  }

  /// 下载文件
  Future download(String url, [String? saveName]) async {
    return DownloadUtils.getInstance().download(
      url,
      saveName,
    );
  }
}

extension SizeExtension on num {
  double get rpx => XAppUtils.getInstance().rpx(this);
}

Color rgba(int r, int g, int b, double a) => Color.fromRGBO(r, g, b, a);
